from typing import List
import datetime
from pydantic import BaseModel, Field, root_validator, validator

from enums.stock_enum import StockTypeEnum


class _BaseStockItem(BaseModel):
    quantity: int = Field(..., description="库存")
    start_date: datetime.date = Field(None, description="开始日期")
    end_date: datetime.date = Field(None, description="结束日期")
    start_time: datetime.time = Field(None, description="开始时间")
    end_time: datetime.time = Field(None, description="结束时间")


class SpecialStockItem(_BaseStockItem):
    sku_id: int = Field(None, description="特殊库存的sku id,如果有设置， 表示这个特殊库存是单独某个sku才有，否则就是spu下所有的sku")


class StockItem(_BaseStockItem):
    ...

    @validator("quantity")
    def validate_quantity(cls, quantity):
        if quantity < 0:
            raise ValueError("库存不能小于0")
        return quantity


class AddNewSPUStockModel(BaseModel):
    # spu_id: int = Field(None, description="spu_id")
    stock_type: StockTypeEnum = Field(..., description="库存类型")
    stock_item_list: List[StockItem] = Field(..., description="库存设置,最多设置一百个区间", max_items=100)
    special_stock_item_list: List[SpecialStockItem] = Field([], description="特殊的库存设置,最多设置一百个特殊区间", max_items=100)
    special_stock_bulk: bool = Field(None, description="特殊库存是否是批量")

    @root_validator()
    def validate_root(cls, attrs: dict):
        stock_type = attrs.get("stock_type")
        special_stock_item_list = attrs.get("special_stock_item_list")
        sku_id_list = []

        if special_stock_item_list:
            for each in special_stock_item_list:
                sku_id = each.dict(exclude_unset=True).get("sku_id")
                if sku_id:
                    sku_id_list.append(sku_id)
            # 要么全部没有，即所有sku都设置这个特殊库存,
            # 要么全部有，即所有sku都有这个特殊库存
            if not (all(sku_id_list) or (all(sku_id_list) is False and any(sku_id_list) is True)):
                raise ValueError("特殊库存设置异常")
            if sku_id_list and all(sku_id_list):
                attrs["special_stock_bulk"] = False
            else:
                attrs["special_stock_bulk"] = True
        if stock_type == StockTypeEnum.total:
            cls._validate_total(attrs.get("stock_item_list"))
            assert not special_stock_item_list, "当前库存类型不允许设置 special_stock_item_list"
        elif stock_type == StockTypeEnum.date:
            cls._validate_date(attrs.get("stock_item_list"))
            if special_stock_item_list:
                cls._validate_date(special_stock_item_list)
        elif stock_type == StockTypeEnum.time:
            cls._validate_time(attrs.get("stock_item_list"))
            if special_stock_item_list:
                cls._validate_time(special_stock_item_list)
        else:
            raise ValueError("暂不支持的库存类型")
        return attrs

    @classmethod
    def _validate_total(cls, stock_item_list):
        for each in stock_item_list:
            for i in ("start_date", "end_date", "start_time", "end_time"):
                assert i not in each, f"当前库存类型不允许设置 {i}"
        return stock_item_list

    @classmethod
    def _validate_date(cls, stock_item_list):
        for each in stock_item_list:
            for i in ("start_time", "end_time"):
                assert i not in each, f"当前库存类型不允许设置 {i}"
            start_date = each.start_date
            end_date = each.end_date
            assert start_date and end_date and start_date <= end_date, "日期设置有误"
        return stock_item_list

    @classmethod
    def _validate_time(cls, stock_item_list):
        for each in stock_item_list:
            for i in ("start_date", "end_date", "start_time", "end_time"):
                assert i in each, f"当前库存类型必须设置: {i}"
            start_date = each.start_date
            end_date = each.end_date
            start_time = each.start_time
            end_time = each.end_time
            assert start_date <= end_date, "开始日期必须小于结束日期"
            assert start_time <= end_time, "开始时间必须小于结束时间"
        return stock_item_list


class UpdateSPUStockModel(AddNewSPUStockModel):
    stock_id: int = Field(None, description="库存id")
    id: int = Field(None, description="库存item的id, 库存id和库存item的id都在的时候， 表示更新，只存在其中一个则异常，两个都不存在表示新建")
